/* 
 * @file   UpgmaAlgorithm.h
 * @author Scanagatta Mauro - Alberto Franco
 *
 * Contains the definitions for the class implementing UPGMA algorithm.
 */
#ifndef UPGMAALGORITHM_H
#define	UPGMAALGORITHM_H

#include <string>
#include <vector>
#include <set>

#include "Align.h"
#include "ScoringS2S.h"
#include "SequenceData.h"
#include "NWAlign.h"
#include "AGPFunction.h"

#include "NewickTree.h"

namespace Biopool
{

class UpgmaAlgorithm 
{
public:
    /// Construct a UPGMA solver from a vector of sequences
    UpgmaAlgorithm(std::vector<std::string> &);
    /// Copy constructor.
    UpgmaAlgorithm(const UpgmaAlgorithm& orig);
    /// Virtual deconstructor
    virtual ~UpgmaAlgorithm();

	/// Runs the algorithm
    std::string execute();

private:

    std::vector<std::string> & sequences;       ///< Input sequences vector
    std::vector<float> distanceMatrix;          ///< Upper sequence distance matrix
    std::vector< NewickTree::Node * > clusters; ///< Vector of clusters

    /// Calculates initial distance matrix
    void calculateInitialDistanceMatrix();
    /// Using Align, calcuate distance between two sequence
    float calculateDistance(std::string, std::string);
    /// Obtains the index of the distances between two sequences.
    int getDistanceIndex(int, int);
    /// Search for minimum distance cluster
    void getMinimumDistance(int &, int &, float &);
    /// Update the clusters. Takes a and b and create a vector k that contains 
    /// both and assign it to a and b is set to zero.
    NewickTree::Node * updateClusters(int, int, float);
    /// Update distance vector after cluster gathering
    void updateDistance(int, int);

    // Align parameters
    int distanceGapPenalty;
    int distanceGapExtension;
    
    // Align classes
	SubMatrix*      subMatrix;
    AlignmentData*  sequenceData;
    GapFunction*    gapFunction;
    ScoringScheme*  scoringScheme;
    Align*          align;
};

} // namespace Biopool

#endif	/* UPGMAALGORITHM_H */
